package com.zp.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zp.api.ApiCode;
import com.zp.api.ApiResult;
import com.zp.domain.ConfigInfo;
import com.zp.util.PropertiesUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;

import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author zp
 * @description
 * @created 2021/12/1 16:02
 */

public class StartReadConfiguration implements EnvironmentAware, ApplicationListener<ContextRefreshedEvent> {

    private StandardEnvironment standardEnvironment;

    private MyBeanDefinitionRegistry myBeanDefinitionRegistry;
    private BeanDefinitionRegistry beanDefinitionRegistry;
    @Autowired
    private ConfigurableApplicationContext applicationContext;
    @Autowired
    private ConfigClientService configClientService;
    private ScheduledExecutorService scheduledService = Executors.newSingleThreadScheduledExecutor();

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        init();
    }

    /**
     * 初始化刷新
     */
    private void init() {
        myBeanDefinitionRegistry = (MyBeanDefinitionRegistry)
                applicationContext.getBeanFactory().getBean("myBeanDefinitionRegistry");
        beanDefinitionRegistry = myBeanDefinitionRegistry.getBeanDefinitionRegistry();
        MutablePropertySources propertySources = standardEnvironment.getPropertySources();
        propertySources.forEach(propertySource -> {
            if (propertySource instanceof OriginTrackedMapPropertySource) {
                OriginTrackedMapPropertySource originTrackedMapPropertySource
                        = (org.springframework.boot.env.OriginTrackedMapPropertySource) propertySource;
                ApiResult apiResult = configClientService.getConfig();
                if (apiResult.getCode()== ApiCode.FAIL.getCode()) {
                    return;
                }
                ConfigInfo configInfo = JSON.toJavaObject(JSON.parseObject(apiResult.getData().toString()), ConfigInfo.class);
                Properties load = PropertiesUtil.load(configInfo.getContent());
                ConfigMd5.setMd5(configInfo.getMd5());
                load.stringPropertyNames().forEach(key->{
                    System.out.println("key:"+key+"\tvalue:"+load.getProperty(key));
                    originTrackedMapPropertySource.getSource().put(key,load.getProperty(key));
                });
                refreshBean();// 刷新配置
                // 开启定时任务检查配置文件是否有发生变化
                scheduledService.scheduleAtFixedRate(new CheckConfigurationFileThread(), 3, 3, TimeUnit.SECONDS);
            }
        });
    }

    private void refreshBean() {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanDefinitionName);
            if ("MyRefresh".equals(beanDefinition.getScope())) {
                applicationContext.getBeanFactory().destroyBean(beanDefinitionName);
                // 卸载该bean
                RefreshScope.getBeans().remove(beanDefinitionName);
                Object bean = applicationContext.getBean(beanDefinitionName);
            }
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.standardEnvironment = (StandardEnvironment) environment;
    }

    class CheckConfigurationFileThread implements Runnable {

        @Override
        public void run() {
            ApiResult apiResult = configClientService.checkConfig();
            if (apiResult.getCode() == ApiCode.SUCCESS.getCode()) {
                return;
            }
            ConfigInfo configInfo = JSON.toJavaObject(JSON.parseObject(apiResult.getData().toString()), ConfigInfo.class);
            Properties load = PropertiesUtil.load(configInfo.getContent());
            MutablePropertySources propertySources = standardEnvironment.getPropertySources();
            propertySources.forEach(propertySource -> {
                if (propertySource instanceof OriginTrackedMapPropertySource) {
                    OriginTrackedMapPropertySource originTrackedMapPropertySource
                            = (org.springframework.boot.env.OriginTrackedMapPropertySource) propertySource;
                    load.stringPropertyNames().forEach(key->{
                        System.out.println("key:"+key+"\tvalue:"+load.getProperty(key));
                        originTrackedMapPropertySource.getSource().put(key,load.getProperty(key));
                    });
                    refreshBean();// 刷新配置
                    ConfigMd5.setMd5(configInfo.getMd5());
                }
            });
        }
    }
}
